﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;
using ArgusLib.Collections;
using ArgusLib.Math;

namespace ArgusLib.Fractals.OrbitFractals
{
	public class DataSetRouteLength : DataSet<Complex>, IDataSetRouteLengths
	{
		double[,] routeLengths;
		double routeLengthLower;
		double routeLengthUpper;

		public IndexedPropertyGet<double, int, int> RouteLengths { get; private set; }
		public DoubleInterval IntervalRouteLengths { get; private set; }
		IParameterIterations IDataSetRouteLengths.CalculationParameter { get { return this.CalculationParameter; } }

		public DataSetRouteLength()
			: base() { }

		public override void Initialize(Parameter parameter)
		{
			base.Initialize(parameter);
			this.routeLengths = new double[parameter.PixelWidth, parameter.PixelHeight];
			this.RouteLengths = new IndexedPropertyGet<double, int, int>(
				new IndexedPropertyGet<double, int, int>.GetHandler(this.get_RouteLengths));
			this.routeLengthLower = double.MaxValue;
			this.routeLengthUpper = double.MinValue;
		}

		protected override void OnZValueChanged(int x, int y, Complex oldValue, Complex newValue)
		{
			this.routeLengths[x, y] += (newValue - oldValue).Magnitude;
			base.OnZValueChanged(x, y, oldValue, newValue);
		}

		protected override void set_IsFinished(int x, int y, bool value)
		{
			base.set_IsFinished(x, y, value);
			double routeLength = this.routeLengths[x, y];
			if (routeLength < this.routeLengthLower)
				this.routeLengthLower = routeLength;
			if (routeLength > this.routeLengthUpper)
				this.routeLengthUpper = routeLength;
		}

		private double get_RouteLengths(int x, int y) { return this.routeLengths[x, y]; }

		public override void PostProcess()
		{
			base.PostProcess();
			this.IntervalRouteLengths = new DoubleInterval(this.routeLengthLower, this.routeLengthUpper);
		}

		public override float GetMemoryUsage(Parameter parameter)
		{
			float baseVal = base.GetMemoryUsage(parameter);
			double bytes = 8.0 * parameter.PixelWidth * parameter.PixelHeight;
			return baseVal + (float)(bytes / (1 << 20));
		}
	}

	public class DataSetRouteLengthProvider : IDataSetProvider
	{
		public IDataSet GetDataSet()
		{
			return new DataSetRouteLength();
		}

		public Type DataSetType { get { return typeof(DataSetRouteLength); } }
	}
}
